"""
交互式叙事组件生成器
生成可交互的 HTML 故事页面，支持动画、选择分支、数据可视化

功能：
1. 生成交互式 HTML 故事页面
2. 支持故事分支选择
3. 嵌入动态图表
4. 添加音效和动画
5. 进度跟踪和保存
"""

from pathlib import Path
from typing import Dict, List, Optional
import json


class InteractiveNarrativeAgent:
    """交互式叙事代理"""
    
    def __init__(self, output_dir: Path, theme: str = "modern"):
        """
        Args:
            output_dir: 输出目录
            theme: 主题风格 (modern, fantasy, sci-fi, minimal)
        """
        self.output_dir = Path(output_dir)
        self.output_dir.mkdir(parents=True, exist_ok=True)
        self.theme = theme
        
        # 主题配置
        self.themes = {
            'modern': {
                'primary': '#3498db',
                'secondary': '#2ecc71',
                'background': '#f8f9fa',
                'text': '#2c3e50',
                'font': 'system-ui, -apple-system, sans-serif'
            },
            'fantasy': {
                'primary': '#8e44ad',
                'secondary': '#e74c3c',
                'background': '#1a1a2e',
                'text': '#eee',
                'font': 'Georgia, serif'
            },
            'sci-fi': {
                'primary': '#00d4ff',
                'secondary': '#ff00ff',
                'background': '#0a0e27',
                'text': '#00ff41',
                'font': 'Courier New, monospace'
            },
            'minimal': {
                'primary': '#333',
                'secondary': '#666',
                'background': '#fff',
                'text': '#333',
                'font': 'Arial, sans-serif'
            }
        }
    
    def generate_interactive_story(self, 
                                   pages: List[str],
                                   title: str = "互动故事",
                                   choices: Optional[Dict] = None,
                                   visualizations: Optional[List] = None) -> str:
        """
        生成完整的交互式故事 HTML
        
        Args:
            pages: 故事页面列表
            title: 故事标题
            choices: 选择分支 {page_index: [{'text': '选项', 'goto': page_index}]}
            visualizations: 可视化数据列表
        
        Returns:
            HTML 文件路径
        """
        theme_config = self.themes.get(self.theme, self.themes['modern'])
        
        html_content = f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{title}</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
    <style>
        * {{
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }}
        
        body {{
            font-family: {theme_config['font']};
            background: {theme_config['background']};
            color: {theme_config['text']};
            line-height: 1.8;
            overflow-x: hidden;
        }}
        
        .container {{
            max-width: 900px;
            margin: 0 auto;
            padding: 40px 20px;
        }}
        
        /* 标题样式 */
        .story-title {{
            text-align: center;
            font-size: 3em;
            margin-bottom: 20px;
            animation: fadeInDown 1s ease;
            background: linear-gradient(135deg, {theme_config['primary']}, {theme_config['secondary']});
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
            background-clip: text;
        }}
        
        /* 进度条 */
        .progress-container {{
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 4px;
            background: rgba(0,0,0,0.1);
            z-index: 1000;
        }}
        
        .progress-bar {{
            height: 100%;
            background: linear-gradient(90deg, {theme_config['primary']}, {theme_config['secondary']});
            width: 0%;
            transition: width 0.3s ease;
        }}
        
        /* 页面卡片 */
        .page-card {{
            background: white;
            border-radius: 20px;
            padding: 40px;
            margin: 30px 0;
            box-shadow: 0 10px 40px rgba(0,0,0,0.1);
            opacity: 0;
            transform: translateY(30px);
            transition: all 0.6s ease;
        }}
        
        .page-card.visible {{
            opacity: 1;
            transform: translateY(0);
        }}
        
        .page-number {{
            display: inline-block;
            background: {theme_config['primary']};
            color: white;
            padding: 5px 15px;
            border-radius: 20px;
            font-size: 0.9em;
            margin-bottom: 20px;
        }}
        
        .page-content {{
            font-size: 1.2em;
            margin: 20px 0;
            text-align: justify;
        }}
        
        /* 选择按钮 */
        .choices {{
            display: flex;
            gap: 15px;
            margin-top: 30px;
            flex-wrap: wrap;
        }}
        
        .choice-btn {{
            flex: 1;
            min-width: 200px;
            padding: 15px 30px;
            background: linear-gradient(135deg, {theme_config['primary']}, {theme_config['secondary']});
            color: white;
            border: none;
            border-radius: 50px;
            font-size: 1.1em;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(0,0,0,0.2);
        }}
        
        .choice-btn:hover {{
            transform: translateY(-3px);
            box-shadow: 0 6px 20px rgba(0,0,0,0.3);
        }}
        
        /* 图表容器 */
        .chart-container {{
            margin: 30px 0;
            padding: 20px;
            background: #f8f9fa;
            border-radius: 15px;
            max-width: 600px;
            margin-left: auto;
            margin-right: auto;
        }}
        
        /* 导航按钮 */
        .navigation {{
            display: flex;
            justify-content: space-between;
            margin-top: 40px;
            gap: 15px;
        }}
        
        .nav-btn {{
            padding: 12px 30px;
            background: {theme_config['text']};
            color: white;
            border: none;
            border-radius: 30px;
            font-size: 1em;
            cursor: pointer;
            transition: all 0.3s ease;
        }}
        
        .nav-btn:hover {{
            opacity: 0.8;
            transform: scale(1.05);
        }}
        
        .nav-btn:disabled {{
            opacity: 0.3;
            cursor: not-allowed;
            transform: none;
        }}
        
        /* 音效控制 */
        .sound-toggle {{
            position: fixed;
            bottom: 30px;
            right: 30px;
            width: 60px;
            height: 60px;
            background: {theme_config['primary']};
            color: white;
            border: none;
            border-radius: 50%;
            font-size: 1.5em;
            cursor: pointer;
            box-shadow: 0 4px 15px rgba(0,0,0,0.3);
            z-index: 999;
            transition: all 0.3s ease;
        }}
        
        .sound-toggle:hover {{
            transform: scale(1.1);
        }}
        
        /* 动画 */
        @keyframes fadeInDown {{
            from {{
                opacity: 0;
                transform: translateY(-30px);
            }}
            to {{
                opacity: 1;
                transform: translateY(0);
            }}
        }}
        
        @keyframes pulse {{
            0%, 100% {{ transform: scale(1); }}
            50% {{ transform: scale(1.05); }}
        }}
        
        /* 深色主题适配 */
        @media (prefers-color-scheme: dark) {{
            .page-card {{
                background: rgba(255,255,255,0.05);
                backdrop-filter: blur(10px);
            }}
        }}
    </style>
</head>
<body>
    <!-- 进度条 -->
    <div class="progress-container">
        <div class="progress-bar" id="progressBar"></div>
    </div>
    
    <!-- 音效控制 -->
    <button class="sound-toggle" id="soundToggle" title="音效开关">🔊</button>
    
    <div class="container">
        <h1 class="story-title">{title}</h1>
        
        <div id="storyContent"></div>
        
        <div class="navigation">
            <button class="nav-btn" id="prevBtn">← 上一页</button>
            <button class="nav-btn" id="nextBtn">下一页 →</button>
        </div>
    </div>
    
    <script>
        // 故事数据
        const storyData = {json.dumps(pages, ensure_ascii=False)};
        const choicesData = {json.dumps(choices or {}, ensure_ascii=False)};
        const vizData = {json.dumps(visualizations or [], ensure_ascii=False)};
        
        let currentPage = 0;
        let soundEnabled = true;
        let visitedPages = new Set([0]);
        
        // 音效
        const sounds = {{
            pageFlip: new Audio('data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBSuBzvLYiTcIGWi77eefTRAMUKfj8LZjHAY4ktfyy3ksBSR3x/DdkEAKFF606+uoVRQKRp/g8r5sIQUrgs7y2Ik3CBlou+3nn00QDFCn4/C2YxwGOJLX8st5LAUkd8fw3ZBAAhRduuvrqFUUCkaf4PK+bCEFK4LO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiS1/LLeSwFJHfH8N2QQAIUXbvr66hVFApGn+Dyvmw='),
            choice: new Audio('data:audio/wav;base64,UklGRnoGAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YQoGAACBhYqFbF1fdJivrJBhNjVgodDbq2EcBj+a2/LDciUFLIHO8tiJNwgZaLvt559NEAxQp+PwtmMcBjiR1/LMeSwFJHfH8N2QQAoUXrTp66hVFApGn+DyvmwhBSuBzvLYiTcIGWi77eefTRAMUKfj8LZjHAY4ktfyy3ksBSR3x/DdkEAKFF606+uoVRQKRp/g8r5sIQUrgs7y2Ik3CBlou+3nn00QDFCn4/C2YxwGOJLX8st5LAUkd8fw3ZBAA')
        }};
        
        // 初始化
        function init() {{
            renderPage(currentPage);
            updateProgress();
            loadProgress();
            
            document.getElementById('prevBtn').addEventListener('click', () => navigatePage(-1));
            document.getElementById('nextBtn').addEventListener('click', () => navigatePage(1));
            document.getElementById('soundToggle').addEventListener('click', toggleSound);
            
            // 键盘导航
            document.addEventListener('keydown', (e) => {{
                if (e.key === 'ArrowLeft') navigatePage(-1);
                if (e.key === 'ArrowRight') navigatePage(1);
            }});
            
            // 自动保存进度
            window.addEventListener('beforeunload', saveProgress);
        }}
        
        // 渲染页面
        function renderPage(pageIndex) {{
            const container = document.getElementById('storyContent');
            container.innerHTML = '';
            
            const pageCard = document.createElement('div');
            pageCard.className = 'page-card';
            
            // 页码
            const pageNumber = document.createElement('div');
            pageNumber.className = 'page-number';
            pageNumber.textContent = `第 ${{pageIndex + 1}} / ${{storyData.length}} 页`;
            pageCard.appendChild(pageNumber);
            
            // 内容
            const content = document.createElement('div');
            content.className = 'page-content';
            content.textContent = storyData[pageIndex];
            pageCard.appendChild(content);
            
            // 可视化
            if (vizData.length > 0) {{
                const viz = vizData.find(v => v.page_index === pageIndex);
                if (viz) {{
                    const chartContainer = document.createElement('div');
                    chartContainer.className = 'chart-container';
                    const canvas = document.createElement('canvas');
                    canvas.id = 'chart_' + pageIndex;
                    chartContainer.appendChild(canvas);
                    pageCard.appendChild(chartContainer);
                    
                    setTimeout(() => renderChart(viz, canvas.id), 300);
                }}
            }}
            
            // 选择分支
            if (choicesData[pageIndex]) {{
                const choicesDiv = document.createElement('div');
                choicesDiv.className = 'choices';
                
                choicesData[pageIndex].forEach(choice => {{
                    const btn = document.createElement('button');
                    btn.className = 'choice-btn';
                    btn.textContent = choice.text;
                    btn.addEventListener('click', () => {{
                        playSound('choice');
                        currentPage = choice.goto;
                        renderPage(currentPage);
                        updateProgress();
                        visitedPages.add(currentPage);
                    }});
                    choicesDiv.appendChild(btn);
                }});
                
                pageCard.appendChild(choicesDiv);
            }}
            
            container.appendChild(pageCard);
            
            // 动画效果
            setTimeout(() => pageCard.classList.add('visible'), 100);
            
            // 更新导航按钮
            document.getElementById('prevBtn').disabled = pageIndex === 0;
            document.getElementById('nextBtn').disabled = pageIndex === storyData.length - 1;
        }}
        
        // 渲染图表
        function renderChart(vizData, canvasId) {{
            const ctx = document.getElementById(canvasId).getContext('2d');
            
            const chartConfig = {{
                type: vizData.chart_type || 'bar',
                data: {{
                    labels: vizData.data.labels,
                    datasets: [{{
                        label: vizData.title,
                        data: vizData.data.values,
                        backgroundColor: [
                            'rgba(52, 152, 219, 0.8)',
                            'rgba(46, 204, 113, 0.8)',
                            'rgba(231, 76, 60, 0.8)',
                            'rgba(241, 196, 15, 0.8)',
                            'rgba(155, 89, 182, 0.8)'
                        ],
                        borderColor: [
                            'rgba(52, 152, 219, 1)',
                            'rgba(46, 204, 113, 1)',
                            'rgba(231, 76, 60, 1)',
                            'rgba(241, 196, 15, 1)',
                            'rgba(155, 89, 182, 1)'
                        ],
                        borderWidth: 2
                    }}]
                }},
                options: {{
                    responsive: true,
                    animation: {{
                        duration: 2000,
                        easing: 'easeOutQuart'
                    }},
                    plugins: {{
                        legend: {{
                            display: vizData.chart_type === 'pie'
                        }},
                        title: {{
                            display: true,
                            text: vizData.title,
                            font: {{ size: 16 }}
                        }}
                    }}
                }}
            }};
            
            new Chart(ctx, chartConfig);
        }}
        
        // 页面导航
        function navigatePage(direction) {{
            const newPage = currentPage + direction;
            if (newPage >= 0 && newPage < storyData.length) {{
                currentPage = newPage;
                renderPage(currentPage);
                updateProgress();
                visitedPages.add(currentPage);
                playSound('pageFlip');
                window.scrollTo({{ top: 0, behavior: 'smooth' }});
            }}
        }}
        
        // 更新进度
        function updateProgress() {{
            const progress = ((currentPage + 1) / storyData.length) * 100;
            document.getElementById('progressBar').style.width = progress + '%';
        }}
        
        // 音效控制
        function toggleSound() {{
            soundEnabled = !soundEnabled;
            document.getElementById('soundToggle').textContent = soundEnabled ? '🔊' : '🔇';
        }}
        
        function playSound(soundName) {{
            if (soundEnabled && sounds[soundName]) {{
                sounds[soundName].currentTime = 0;
                sounds[soundName].play().catch(e => console.log('Sound play failed:', e));
            }}
        }}
        
        // 进度保存/加载
        function saveProgress() {{
            localStorage.setItem('storyProgress', JSON.stringify({{
                currentPage,
                visitedPages: Array.from(visitedPages)
            }}));
        }}
        
        function loadProgress() {{
            const saved = localStorage.getItem('storyProgress');
            if (saved) {{
                const data = JSON.parse(saved);
                if (confirm('检测到上次的阅读进度，是否继续？')) {{
                    currentPage = data.currentPage;
                    visitedPages = new Set(data.visitedPages);
                    renderPage(currentPage);
                    updateProgress();
                }}
            }}
        }}
        
        // 启动
        init();
    </script>
</body>
</html>"""
        
        # 保存 HTML
        output_path = self.output_dir / f"{title}.html"
        with open(output_path, 'w', encoding='utf-8') as f:
            f.write(html_content)
        
        print(f"✅ 交互式故事已生成: {output_path}")
        return str(output_path)
    
    def create_choice_based_story(self, story_tree: Dict) -> str:
        """
        创建基于选择的分支故事
        
        Args:
            story_tree: 故事树结构 {
                'title': str,
                'nodes': {
                    0: {'text': str, 'choices': [{'text': str, 'goto': int}]},
                    ...
                }
            }
        """
        pages = []
        choices = {}
        
        for node_id, node_data in story_tree['nodes'].items():
            pages.append(node_data['text'])
            if 'choices' in node_data:
                choices[int(node_id)] = node_data['choices']
        
        return self.generate_interactive_story(
            pages=pages,
            title=story_tree.get('title', '选择你的冒险'),
            choices=choices
        )


# ==================== 使用示例 ====================

if __name__ == "__main__":
    output_dir = Path("interactive_stories")
    agent = InteractiveNarrativeAgent(output_dir, theme="fantasy")
    
    # 示例1: 线性故事 + 可视化
    pages = [
        "从前有一个勇敢的骑士，他踏上了寻找传说中圣剑的旅程。",
        "他的力量值85，智慧92，速度78，魔法95，防御88。这些属性将决定他的命运。",
        "第一天，他在森林中遇到了强大的怪物。经过激烈的战斗，他获得了100点经验。",
        "随着冒险的深入，他的经验值不断增长：第2天250点，第3天580点，第4天1200点，第5天达到了2500点！",
        "他收集的装备越来越多：武器占40%，护甲30%，饰品20%，其他10%。",
        "最终，他找到了圣剑，成为了传奇英雄！"
    ]
    
    visualizations = [
        {
            'page_index': 1,
            'chart_type': 'bar',
            'title': '骑士属性',
            'data': {
                'labels': ['力量', '智慧', '速度', '魔法', '防御'],
                'values': [85, 92, 78, 95, 88]
            }
        },
        {
            'page_index': 3,
            'chart_type': 'line',
            'title': '经验值增长',
            'data': {
                'labels': ['第1天', '第2天', '第3天', '第4天', '第5天'],
                'values': [100, 250, 580, 1200, 2500]
            }
        },
        {
            'page_index': 4,
            'chart_type': 'pie',
            'title': '装备分布',
            'data': {
                'labels': ['武器', '护甲', '饰品', '其他'],
                'values': [40, 30, 20, 10]
            }
        }
    ]
    
    path1 = agent.generate_interactive_story(
        pages=pages,
        title="骑士的传说",
        visualizations=visualizations
    )
    
    print(f"\n📖 线性故事已生成: {path1}")
    
    # 示例2: 分支选择故事
    story_tree = {
        'title': '神秘的森林',
        'nodes': {
            0: {
                'text': '你站在一片神秘森林的入口。前方有两条路：左边的路黑暗而危险，右边的路明亮而平坦。',
                'choices': [
                    {'text': '选择左边的危险之路', 'goto': 1},
                    {'text': '选择右边的平坦之路', 'goto': 2}
                ]
            },
            1: {
                'text': '你选择了危险之路。突然，一只巨大的狼出现了！你必须做出选择。',
                'choices': [
                    {'text': '勇敢战斗', 'goto': 3},
                    {'text': '尝试逃跑', 'goto': 4}
                ]
            },
            2: {
                'text': '你选择了平坦之路。一路上风景优美，你遇到了一个友善的精灵。',
                'choices': [
                    {'text': '向精灵请教', 'goto': 5},
                    {'text': '继续前进', 'goto': 6}
                ]
            },
            3: {
                'text': '你勇敢地与狼战斗，最终获胜！你获得了珍贵的宝石。冒险成功！'
            },
            4: {
                'text': '你试图逃跑，但不幸被狼追上了。游戏结束。'
            },
            5: {
                'text': '精灵告诉你森林的秘密，并赠送你魔法护身符。你平安通过了森林！'
            },
            6: {
                'text': '你继续前进，但迷失在了森林深处。游戏结束。'
            }
        }
    }
    
    path2 = agent.create_choice_based_story(story_tree)
    print(f"🎮 分支故事已生成: {path2}")
    
    print("\n" + "="*70)
    print("✅ 所有交互式故事已生成！")
    print(f"📁 保存位置: {output_dir.absolute()}")
    print("💡 用浏览器打开 HTML 文件即可体验")
    print("="*70)